using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Windows.Forms;

namespace 图片分辨率转换
{
    public partial class MainForm : Form
    {
        private readonly HashSet<string> _addedImagePaths = new HashSet<string>();
        private readonly Dictionary<string, (int Width, int Height)> _originalImageSizes = new Dictionary<string, (int, int)>();
        private bool _isUserModifiedWidth = false;
        private bool _isUserModifiedHeight = false;
        private bool _isUserModifiedRatio = false; // 标记用户是否手动修改过比例

        public MainForm()
        {
            InitializeComponent();
            // 初始化列表
            lstImages.View = View.Details;
            lstImages.FullRowSelect = true;
            lstImages.GridLines = true;
            lstImages.MultiSelect = true;
            lstImages.Columns.Add("文件名", 180);
            lstImages.Columns.Add("大小(KB)", 80);
            lstImages.Columns.Add("格式", 60);
            lstImages.Columns.Add("分辨率", 100);
            lstImages.Columns.Add("修改日期", 150);

            // 绑定事件：列表变化时更新默认宽高和比例
            lstImages.SelectedIndexChanged += (s, e) => UpdateDefaultSizeAndRatio();
            lstImages.Items.Clear();

            // 绑定用户输入事件（目标宽高）
            txtWidth.TextChanged += (s, e) => _isUserModifiedWidth = true;
            txtHeight.TextChanged += (s, e) => _isUserModifiedHeight = true;

            // 绑定比例文本框事件（验证输入+标记手动修改）
            txtRatioWidth.TextChanged += (s, e) =>
            {
                if (int.TryParse(txtRatioWidth.Text, out int val) && val > 0)
                {
                    _isUserModifiedRatio = true;
                    if (chkKeepRatio.Checked) UpdateRatioReference(); // 实时更新目标宽高
                }
                else if (!string.IsNullOrEmpty(txtRatioWidth.Text))
                {
                    AddStatus("比例宽度必须是正整数！");
                }
            };
            txtRatioHeight.TextChanged += (s, e) =>
            {
                if (int.TryParse(txtRatioHeight.Text, out int val) && val > 0)
                {
                    _isUserModifiedRatio = true;
                    if (chkKeepRatio.Checked) UpdateRatioReference(); // 实时更新目标宽高
                }
                else if (!string.IsNullOrEmpty(txtRatioHeight.Text))
                {
                    AddStatus("比例高度必须是正整数！");
                }
            };

            // 保持等比例复选框状态变化时，更新比例文本框可用性
            chkKeepRatio.CheckedChanged += (s, e) =>
            {
                txtRatioWidth.Enabled = chkKeepRatio.Checked;
                txtRatioHeight.Enabled = chkKeepRatio.Checked;
                lblColon.Enabled = chkKeepRatio.Checked;
            };
        }

        // 核心方法：更新默认宽高和比例文本框
        private void UpdateDefaultSizeAndRatio()
        {
            if (lstImages.Items.Count == 0)
            {
                txtRatioWidth.Text = "";
                txtRatioHeight.Text = "";
                return;
            }

            // 获取参考图片（列表第一张）
            var firstItem = lstImages.Items[0];
            string firstImagePath = firstItem.Tag.ToString();
            if (!_originalImageSizes.TryGetValue(firstImagePath, out var firstImageSize))
            {
                txtRatioWidth.Text = "";
                txtRatioHeight.Text = "";
                return;
            }

            // 更新默认宽高（用户未手动修改时）
            if (!_isUserModifiedWidth)
            {
                txtWidth.Text = firstImageSize.Width.ToString();
            }
            if (!_isUserModifiedHeight)
            {
                txtHeight.Text = firstImageSize.Height.ToString();
            }

            // 更新比例文本框（用户未手动修改比例时）
            if (!_isUserModifiedRatio)
            {
                var (ratioW, ratioH) = GetSimplifiedRatio(firstImageSize.Width, firstImageSize.Height);
                txtRatioWidth.Text = ratioW.ToString();
                txtRatioHeight.Text = ratioH.ToString();
            }
        }

        // 计算宽高的最简整数比（返回宽和高的比例值）
        private (int RatioWidth, int RatioHeight) GetSimplifiedRatio(int width, int height)
        {
            if (height == 0) return (1, 1); // 避免除零

            int gcd = GCD(width, height);
            return (width / gcd, height / gcd);
        }

        // 求最大公约数（欧几里得算法）
        private int GCD(int a, int b)
        {
            a = Math.Abs(a);
            b = Math.Abs(b);
            while (b != 0)
            {
                int temp = b;
                b = a % b;
                a = temp;
            }
            return a;
        }

        // 基于比例文本框的值计算等比例宽高
        private void UpdateRatioReference()
        {
            if (!chkKeepRatio.Checked || !int.TryParse(txtRatioWidth.Text, out int ratioW) || !int.TryParse(txtRatioHeight.Text, out int ratioH) || ratioW <= 0 || ratioH <= 0)
                return;

            // 计算比例系数
            double ratio = (double)ratioW / ratioH;
            var activeTextBox = txtWidth.Focused ? txtWidth : (txtHeight.Focused ? txtHeight : null);

            if (activeTextBox == txtWidth && int.TryParse(txtWidth.Text, out int newWidth) && newWidth > 0)
            {
                // 根据宽度和比例计算高度
                txtHeight.TextChanged -= txtWidth_TextChanged;
                txtHeight.Text = ((int)Math.Round(newWidth / ratio)).ToString();
                txtHeight.TextChanged += txtWidth_TextChanged;
            }
            else if (activeTextBox == txtHeight && int.TryParse(txtHeight.Text, out int newHeight) && newHeight > 0)
            {
                // 根据高度和比例计算宽度
                txtWidth.TextChanged -= txtWidth_TextChanged;
                txtWidth.Text = ((int)Math.Round(newHeight * ratio)).ToString();
                txtWidth.TextChanged += txtWidth_TextChanged;
            }
        }

        // 浏览文件夹添加图片
        private void btnSelectFolder_Click(object sender, EventArgs e)
        {
            using (var fbd = new FolderBrowserDialog())
            {
                if (fbd.ShowDialog() == DialogResult.OK)
                {
                    string folderPath = fbd.SelectedPath;
                    txtFolderPath.Text = folderPath;
                    AddImagesFromFolder(folderPath);
                }
            }
        }

        // 从文件夹添加图片（添加后更新比例）
        private void AddImagesFromFolder(string folderPath)
        {
            if (!Directory.Exists(folderPath))
            {
                AddStatus($"文件夹不存在：{folderPath}");
                return;
            }

            var supportedExts = new[] { ".jpg", ".jpeg", ".png", ".bmp", ".gif", ".tiff" };
            int addedCount = 0;
            bool wasEmpty = lstImages.Items.Count == 0;

            foreach (var filePath in Directory.GetFiles(folderPath))
            {
                var ext = Path.GetExtension(filePath).ToLower();
                if (!supportedExts.Contains(ext)) continue;
                if (_addedImagePaths.Contains(filePath)) continue;

                try
                {
                    var fileInfo = new FileInfo(filePath);
                    string fileName = Path.GetFileName(filePath);
                    string fileSize = $"{fileInfo.Length / 1024.0:F1}";
                    string fileFormat = ext.ToUpper().Trim('.');
                    string modifyDate = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss");
                    string resolution = "未知";

                    using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                    using (var img = Image.FromStream(fs))
                    {
                        int originalWidth = img.Width;
                        int originalHeight = img.Height;
                        resolution = $"{originalWidth}×{originalHeight}";
                        _originalImageSizes[filePath] = (originalWidth, originalHeight);
                    }

                    var item = new ListViewItem(fileName);
                    item.SubItems.Add(fileSize);
                    item.SubItems.Add(fileFormat);
                    item.SubItems.Add(resolution);
                    item.SubItems.Add(modifyDate);
                    item.Tag = filePath;
                    lstImages.Items.Add(item);
                    _addedImagePaths.Add(filePath);
                    addedCount++;
                }
                catch (Exception ex)
                {
                    AddStatus($"添加失败「{Path.GetFileName(filePath)}」：{ex.Message}");
                }
            }

            AddStatus($"从文件夹追加 {addedCount} 张图片");
            if (wasEmpty && addedCount > 0)
            {
                UpdateDefaultSizeAndRatio();
            }
        }

        // 手动添加图片（添加后更新比例）
        private void btnAdd_Click(object sender, EventArgs e)
        {
            using (var ofd = new OpenFileDialog())
            {
                ofd.Title = "选择要添加的图片（可多选）";
                ofd.Filter = "图片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif;*.tiff|所有文件|*.*";
                ofd.Multiselect = true;

                if (ofd.ShowDialog() != DialogResult.OK) return;

                int addedCount = 0;
                bool wasEmpty = lstImages.Items.Count == 0;

                foreach (var filePath in ofd.FileNames)
                {
                    if (_addedImagePaths.Contains(filePath)) continue;

                    try
                    {
                        var fileInfo = new FileInfo(filePath);
                        string fileName = Path.GetFileName(filePath);
                        string fileSize = $"{fileInfo.Length / 1024.0:F1}";
                        string ext = Path.GetExtension(filePath).ToLower();
                        string fileFormat = ext.ToUpper().Trim('.');
                        string modifyDate = fileInfo.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss");
                        string resolution = "未知";

                        using (var fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
                        using (var img = Image.FromStream(fs))
                        {
                            int originalWidth = img.Width;
                            int originalHeight = img.Height;
                            resolution = $"{originalWidth}×{originalHeight}";
                            _originalImageSizes[filePath] = (originalWidth, originalHeight);
                        }

                        var item = new ListViewItem(fileName);
                        item.SubItems.Add(fileSize);
                        item.SubItems.Add(fileFormat);
                        item.SubItems.Add(resolution);
                        item.SubItems.Add(modifyDate);
                        item.Tag = filePath;
                        lstImages.Items.Add(item);
                        _addedImagePaths.Add(filePath);
                        addedCount++;
                    }
                    catch (Exception ex)
                    {
                        AddStatus($"添加失败「{Path.GetFileName(filePath)}」：{ex.Message}");
                    }
                }

                AddStatus($"共添加 {addedCount} 张图片");
                MessageBox.Show($"添加完成！成功添加 {addedCount} 张图片", "结果", MessageBoxButtons.OK, MessageBoxIcon.Information);
                if (wasEmpty && addedCount > 0)
                {
                    UpdateDefaultSizeAndRatio();
                }
            }
        }

        // 移除图片（移除后更新比例）
        private void btnDelete_Click(object sender, EventArgs e)
        {
            if (lstImages.SelectedItems.Count == 0)
            {
                MessageBox.Show("请先选中要移除的图片！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }

            int count = lstImages.SelectedItems.Count;
            var names = lstImages.SelectedItems.Cast<ListViewItem>().Take(5).Select(i => i.Text);
            string msg = $"确定移除选中的 {count} 张图片？\n包含：{string.Join("、", names)}{(count > 5 ? " 等" : "")}";

            if (MessageBox.Show(msg, "确认移除", MessageBoxButtons.YesNo, MessageBoxIcon.Information) == DialogResult.Yes)
            {
                bool wasLastItem = lstImages.Items.Count == count;

                for (int i = lstImages.SelectedItems.Count - 1; i >= 0; i--)
                {
                    var item = lstImages.SelectedItems[i];
                    string path = item.Tag.ToString();
                    lstImages.Items.Remove(item);
                    _addedImagePaths.Remove(path);
                    _originalImageSizes.Remove(path);
                    AddStatus($"已移除：{item.Text}");
                }

                AddStatus($"共移除 {count} 张图片");

                if (lstImages.Items.Count > 0 && !wasLastItem && !_isUserModifiedRatio)
                {
                    UpdateDefaultSizeAndRatio(); // 未手动修改比例时更新
                }
                else if (lstImages.Items.Count == 0)
                {
                    txtRatioWidth.Text = "";
                    txtRatioHeight.Text = "";
                }
            }
        }

        // 宽高文本框变化时触发等比例计算
        private void txtWidth_TextChanged(object sender, EventArgs e)
        {
            if (chkKeepRatio.Checked && lstImages.Items.Count > 0)
            {
                UpdateRatioReference();
            }
        }

        // 处理图片
        private void btnProcess_Click(object sender, EventArgs e)
        {
            if (lstImages.Items.Count == 0)
            {
                MessageBox.Show("列表中没有可处理的图片！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            if (!int.TryParse(txtWidth.Text, out int targetWidth) || targetWidth <= 0)
            {
                MessageBox.Show("请输入有效的目标宽度！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }
            if (!int.TryParse(txtHeight.Text, out int targetHeight) || targetHeight <= 0)
            {
                MessageBox.Show("请输入有效的目标高度！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            ProcessImages(targetWidth, targetHeight);
        }

        // 批量处理图片
        private void ProcessImages(int targetWidth, int targetHeight)
        {
            string targetFolderName = $"分辨率{targetWidth}x{targetHeight}";
            int success = 0, failed = 0;

            AddStatus($"开始处理 {lstImages.Items.Count} 张图片，目标分辨率：{targetWidth}×{targetHeight}");

            foreach (ListViewItem item in lstImages.Items)
            {
                string sourcePath = item.Tag.ToString();
                string fileName = item.Text;

                if (!File.Exists(sourcePath))
                {
                    AddStatus($"失败：{fileName}（文件不存在）");
                    failed++;
                    continue;
                }

                try
                {
                    string sourceDir = Path.GetDirectoryName(sourcePath);
                    string targetDir = Path.Combine(sourceDir, targetFolderName);
                    Directory.CreateDirectory(targetDir);
                    string targetPath = Path.Combine(targetDir, fileName);

                    ResizeImage(sourcePath, targetWidth, targetHeight, targetPath);
                    success++;
                    AddStatus($"成功：{fileName}（保存至 {targetFolderName}）");
                }
                catch (Exception ex)
                {
                    failed++;
                    AddStatus($"失败：{fileName}，原因：{ex.Message}");
                }
            }

            AddStatus($"处理完成：成功 {success} 张，失败 {failed} 张");
            MessageBox.Show($"处理完成！成功 {success} 张，失败 {failed} 张", "结果", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        // 添加状态信息
        private void AddStatus(string message)
        {
            if (lstStatus.InvokeRequired)
            {
                lstStatus.Invoke(new Action<string>(AddStatus), message);
                return;
            }
            lstStatus.Items.Add($"[{DateTime.Now:HH:mm:ss}] {message}");
            lstStatus.TopIndex = lstStatus.Items.Count - 1;
        }

        // 调整图片大小
        private void ResizeImage(string sourcePath, int width, int height, string targetPath)
        {
            using (var original = Image.FromFile(sourcePath))
            using (var resized = new Bitmap(width, height))
            using (var g = Graphics.FromImage(resized))
            {
                g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                g.DrawImage(original, 0, 0, width, height);
                resized.Save(targetPath, GetImageFormat(Path.GetExtension(sourcePath)));
            }
        }

        // 获取图片格式
        private ImageFormat GetImageFormat(string extension)
        {
            return extension.ToLower() switch
            {
                ".jpg" or ".jpeg" => ImageFormat.Jpeg,
                ".png" => ImageFormat.Png,
                ".bmp" => ImageFormat.Bmp,
                ".gif" => ImageFormat.Gif,
                ".tiff" => ImageFormat.Tiff,
                _ => ImageFormat.Jpeg
            };
        }
    }
}